#pragma once
#include <memory>
#include <vector>
#include "safety/io/safeiotype.h"
namespace safety {

enum class SafeStat
{
    Safe,
    UnSafe,
    Fault
};

class SafeInput
{
public:
    SafeInput() {}
    virtual SafeStat update_new_state() = 0;

protected:
    bool signal[2] = {true, true};
    bool fault = 0;
};
class UsrSafeInputChannels
{
public:
    UsrSafeInputChannels();
    virtual int config_channel(int chnid);

protected:
    int channel_;
};

class BpEstop : public SafeInput
{
public:
    BpEstop();
    SafeStat update_new_state() override;
};
class SysEstop : public SafeInput
{
public:
    SysEstop();
    SafeStat update_new_state() override;
};

/**
 * @brief 急停事件，动作为CAT0
 */
class EStopEvent
{
public:
    EStopEvent();
    ~EStopEvent();
    int check();
    void reset();
    inline bool is_safe() const { return state_ == SafeStat::Safe; }
    inline bool is_fault() const { return state_ == SafeStat::Fault; }

private:
    SafeStat state_ = SafeStat::Safe;
    std::vector<std::shared_ptr<SafeInput>> inputs_;

    BpEstop bp_estop_;    //手柄急停信号
    SysEstop sys_estop_;  //系统急停信号

    bool enable_manual_reset_ = false;  //开启手动复位模式
};

class ScbPStop : public SafeInput
{
public:
    ScbPStop();
    SafeStat update_new_state() override;
};

/**
 * @brief 保护性停止
 */
class ProtectiveStopEvent
{
public:
    ProtectiveStopEvent();
    ~ProtectiveStopEvent() {}
    int check();
    void reset();
    inline bool is_safe() const { return state_ == SafeStat::Safe; }
    inline bool is_fault() const { return state_ == SafeStat::Fault; }

private:
    SafeStat state_ = SafeStat::Safe;
    std::vector<std::shared_ptr<SafeInput>> inputs_;

    ScbPStop bp_estop_;                 //系统保护性停止
    bool enable_manual_reset_ = false;  //开启手动复位模式
};

class SafeIOMgr
{
public:
    static SafeIOMgr& instance();
    int init();
    SafeIO_ConfigParam load_config(std::string cfgfile);
    int save_config(std::string cfgfile, SafeIO_ConfigParam* cfg);

    /**
     * @brief 读取用户安全输入通道,用于给APP显示
     * @param safein 用户安全输入通道的配置，按照ch1,ch2,ch3,ch4的顺序
     */
    virtual int get_user_safein(std::vector<SafeIO_UsrSafeInputEv>& safein);
    /**
     * @brief APP配置用户安全输入通道
     * @param safein 用户安全输入通道的配置，按照ch1,ch2,ch3,ch4的顺序
     */
    virtual int set_user_safein(const std::vector<SafeIO_UsrSafeInputEv>& safein);

    /**
     * @brief 读取用户安全输出通道,用于给APP显示
     */
    virtual int get_user_safeout(std::vector<SafeIO_UsrSafeOutputEv>& safeout);

    /**
     * @brief APP配置用户安全输出通道
     */
    virtual int set_user_safeout(const std::vector<SafeIO_UsrSafeOutputEv>& safeout);

    inline bool is_estop() const { return !estop.is_safe(); }
    inline bool is_protective_stop() { return !pstop.is_safe(); }
    bool is_reduce_mode();

public:
    void update();

private:
    SafeIOMgr();

private:
    SafeIO_ConfigParam config_;
    EStopEvent estop;           // 急停
    ProtectiveStopEvent pstop;  // 保护性停止
    // std::shared_ptr<SafeEvent> moving;                   // 机器人运动状态
    // std::shared_ptr<SafeEvent> estop;                    // 机器人停止，关闭电源
    // std::shared_ptr<SafeEvent> cat2_stop;                // 机器人停止，保持使能
    // std::shared_ptr<SafeEvent> cat1_stop;                // 机器人停止，关闭使能，比如三位使能，保护性停止
    // std::shared_ptr<SafeEvent> three_position_enabling;  // 三位使能
    // std::shared_ptr<SafeEvent> reduce_mode;              // 缩减模式
    // std::shared_ptr<SafeEvent> set_collision_lv;         // 限定碰撞监控等级
};

void check_safety_io();
void get_safety_IO_status();
void set_safety_IO_status();
}  // namespace safety
